package edu.umd.ion.wavemeter.client;

import java.util.Date;

import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.BeforeSelectionEvent;
import com.google.gwt.event.logical.shared.BeforeSelectionHandler;
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.ResponseTextHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.MultiWordSuggestOracle;
import com.google.gwt.user.client.ui.SuggestBox;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.xml.client.XMLParser;
import com.google.gwt.xml.client.Document;

import edu.umd.ion.wavemeter.service.WavemeterParameters;
import edu.umd.ion.wavemeter.service.WavemeterServiceAsync;


public class Settings extends Composite implements
		BeforeSelectionHandler<Integer> {
	public TextArea WavemeterWidgetSettings;
	HTML ErrorLabel = new HTML();
	SuggestBox Usernamebox = new SuggestBox( new MultiWordSuggestOracle() ); 
	
	String Name;
	String CurrentSettings;
	String Username = "default";
	ResponseTextHandler Callback;
	
	private WavemeterServiceAsync serviceProxy;

	public void setErrorMessage(String message) {
		ErrorLabel.setHTML(message);
	}
	
	public String myUsername() {
		return Username;
	}
	
	private AsyncCallback<String> SettingsCallback = new AsyncCallback<String>()
	{
		public void onFailure (Throwable caught)
		{
			try {
				ErrorLabel.setHTML( "Settings: " + caught.getMessage() );
				throw caught;
			} catch (IncompatibleRemoteServiceException e) {
				// this client is not compatible with the server; cleanup and refresh the 
				// browser
			} catch (Throwable e) {
				// last resort -- a very unexpected exception
			}
		}
		public void onSuccess (String settings)
		{
			if (settings!=null) {
				ErrorLabel.setHTML("");
				CurrentSettings = settings;
				WavemeterWidgetSettings.setText(CurrentSettings);
				Callback.onCompletion(CurrentSettings);
			} else {
				ErrorLabel.setHTML("No settings exist");
				CurrentSettings = new String();
				WavemeterWidgetSettings.setText(CurrentSettings);
			}
		}
	};

	private AsyncCallback<String[]> UsernamesCallback = new AsyncCallback<String[]>()
	{
		public void onFailure (Throwable caught)
		{
			try {
				throw caught;
			} catch (IncompatibleRemoteServiceException e) {
				// this client is not compatible with the server; cleanup and refresh the 
				// browser
			} catch (Throwable e) {
				// last resort -- a very unexpected exception
			}
		}
		public void onSuccess (String[] usernames)
		{
			MultiWordSuggestOracle oracle = (MultiWordSuggestOracle) Usernamebox.getSuggestOracle();  
			for (int i=0; i<usernames.length; ++i) {
				oracle.add(usernames[i]);
			}
		}
	};

	private AsyncCallback<Void> CommandCallback = new AsyncCallback<Void>() {
		public void onFailure(Throwable caught) {
			try {
				ErrorLabel.setHTML("Command: " + caught.getMessage());
				throw caught;
			} catch (IncompatibleRemoteServiceException e) {
				// this client is not compatible with the server; cleanup and refresh the 
				// browser
			} catch (Throwable e) {
				// last resort -- a very unexpected exception
			}			
		}

		public void onSuccess(Void result) {
			ErrorLabel.setHTML("");
		}
	};

	private ChangeHandler UsernameChangeListener = new ChangeHandler() {
		public void onChange(ChangeEvent e) {
			setUsername( Usernamebox.getText() );
		}
	};

	@Override
	public void onBeforeSelection(BeforeSelectionEvent<Integer> event) {
		serviceProxy.getUsernames(UsernamesCallback);
	}
	
	public String getSettings()
	{
		return CurrentSettings;
	}
	
	public void setUsername(String username) {
		Username = username;
		Date Now = new Date();
		Cookies.setCookie(WavemeterParameters.Username, Username, new Date(Now.getTime()+100000000000L) );
	}
	
	public void applySettings()
	{
		try {
			ErrorLabel.setHTML("");
			CurrentSettings = WavemeterWidgetSettings.getText();
			Callback.onCompletion(CurrentSettings);
		} catch (Exception ex)	{
			ErrorLabel.setHTML(ex.getMessage());
		}
	}

	public void loadSettings() {
		setUsername(Usernamebox.getText());
		serviceProxy.getSettings(Username, SettingsCallback);
	}
	
	public void saveSettings() {
		setUsername(Usernamebox.getText());
		serviceProxy.setSettings(Username, WavemeterWidgetSettings.getText(), CommandCallback );
	}
	
	public Document getDocument()
	{
		return XMLParser.parse(CurrentSettings);
	}
	
	public Settings( WavemeterServiceAsync service, ResponseTextHandler handler )
	{
		serviceProxy = service;
		Callback = handler;
		String NewUsername = Cookies.getCookie(WavemeterParameters.Username);
		if (NewUsername!=null) Username = NewUsername;
		
	    VerticalPanel vert = new VerticalPanel();
	    vert.setWidth("100%");
	    
	    HorizontalPanel UsernameLine = new HorizontalPanel();
	    UsernameLine.add( new Label("Username: "));
	    Usernamebox.setTitle("Usernamebox Title");
	    Usernamebox.setText(Username);
	    Usernamebox.getTextBox().addChangeHandler(UsernameChangeListener);
	    UsernameLine.add( Usernamebox );
	    UsernameLine.add(new Button("Apply",  new ClickHandler() { 
			public void onClick(ClickEvent e){ applySettings();  } }   ));
	    UsernameLine.add(new Button("Save", new ClickHandler() { 
			public void onClick(ClickEvent e){ saveSettings();  } } ));
	    UsernameLine.add(new Button("Load", new ClickHandler() { 
			public void onClick(ClickEvent e){ loadSettings(); 
			 } } ));

	    WavemeterWidgetSettings = new TextArea();
		WavemeterWidgetSettings.setHeight("500px");
		WavemeterWidgetSettings.setWidth("100%");
				 		
		vert.add(UsernameLine);
		vert.add(WavemeterWidgetSettings);
		vert.add( ErrorLabel );
		initWidget( vert );
		
		loadSettings();
	}
}	
